package dormouse.vfs.ui;

/**
 * This class represents a single node in a file tree.
 * 
 */

import java.io.File;

import javax.swing.tree.DefaultMutableTreeNode;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.VFS;

import dormouse.vfs.FileUtil;

/**
 * This class is used to render a file object as a tree node in a Swing JTree. 
 */
public class FileNode extends DefaultMutableTreeNode {
	
	/** Serial Version UID. */
	private static final long serialVersionUID = 2189111878864756827L;
	
	private boolean explored = false;

	/**
	 * Constructor
	 * 
	 * @param file
	 */
	public FileNode(FileObject file) {
		setUserObject(new SelectableFile(file));
	}

	/**
	 * Constructor
	 * 
	 * @param file
	 */
	public FileNode(File file) {
		setUserObject(new SelectableFile(file));
	}

	public FileNode(String path) {
		try {
			setUserObject(VFS.getManager().resolveFile(path));
		} catch (FileSystemException e) {
			e.printStackTrace();
		}
	}

	/**
	 * This method determines if the node allows children.
	 * 
	 * @return
	 */
	public boolean getAllowsChildren() {
		return isDirectory();
	}

	/**
	 * This method determines if the file node is a leaf node or not by
	 * determining if the file is a directory.
	 * 
	 * @return True if the file is not a directory, false otherwise.
	 */
	public boolean isLeaf() {
		return !isDirectory();
	}

	/**
	 * This method gets the file. The file is stored in the FileNode's
	 * userObject.
	 * 
	 * @return
	 */
	public FileObject getFile() {
		SelectableFile sf = (SelectableFile) getUserObject();
		return (FileObject) sf.getFile();
	}

	/**
	 * This method determines if the file is selected.
	 * 
	 * @return true, if the file is selected; false, otherwise.
	 */
	public boolean isSelected() {
		SelectableFile sf = (SelectableFile) getUserObject();
		return sf.isSelected();
	}

	/**
	 * This method sets whether or not the node is selected.
	 * 
	 * @param selected
	 *            True if the file is selected, false otherwise
	 */
	public void setSelected(boolean selected) {
		SelectableFile sf = (SelectableFile) getUserObject();
		sf.setSelected(selected);
	}

	/**
	 * This method determines if the file is a directory.
	 * 
	 * @return true, if the file is a directory; false, otherwise.
	 */
	public boolean isDirectory() {
		FileType type = null;
		try {
			type = getFile().getType();
		} catch (FileSystemException e) {
			e.printStackTrace();
		}
		return (type == FileType.FOLDER);
	}

	/**
	 * This method gets the name of the file.
	 * 
	 * @return
	 */
	public String toString() {
		FileObject file = getFile();
		return file.getName().getBaseName();
	}

	/**
	 * This overload of the explore method gets a list of child directories only
	 * if the the current directory has not yet been explored.
	 */
	public void explore() {
		explore(false);
	}

	/**
	 * This method determines if the directory has already been explored.
	 * 
	 * @return
	 */
	public boolean isExplored() {
		return explored;
	}

	/**
	 * This method allows the user to explore a subdirectory and find all of the
	 * child directories from a given parent directory.
	 * 
	 * @param force
	 *            Determines if the all directories should be explored again
	 *            regardless of whether or not they've been explored before.
	 */
	public void explore(boolean force) {
		if (!isExplored() || force) {
			FileObject file = getFile();

			// find all child directories
			FileObject[] children = null;
			try {
				children = FileUtil.getChildDirectories(file);
			} catch (FileSystemException e) {
				e.printStackTrace();
			}
			if (children != null) {
				int numChildren = children.length;
				for (int i = 0; i < numChildren; ++i) {
					add(new FileNode(children[i]));
				}
			}

			explored = true;
		}
	}
}